import {
  Button,
  Form,
  FormItem,
  Input,
  Modal,
  notification,
  Radio,
  RadioGroup,
  RangePicker,
  Space,
  Spin,
  Upload
} from 'ant-design-vue'
import { omit } from 'lodash-es'
import { computed, defineComponent, onMounted, ref, watch } from 'vue'
import { useRoute } from 'vue-router'

import { couponApi } from '@/apis'
import { SvgIcon } from '@/components'
import { useBack } from '@/hooks'
import { download, downloadLink } from '@/utils'

import styles from './index.module.css'

const { useForm } = Form

export default defineComponent({
  name: 'CouponForm',
  props: {
    isEdit: { type: Boolean, default: false },
    isValid: { type: Boolean, default: false }
  },
  setup(props) {
    const loading = ref(false)
    const route = useRoute()
    const formModel = ref({
      name: '',
      couponType: 1,
      generateType: 1,
      stock: '',
      perPersonLimit: '',
      date: [],
      discountAmount: '',
      discount: '',
      serialNumber: ''
    })
    const formRules = ref({
      name: [{ required: true, message: '请输入', trigger: 'blur' }],
      couponType: [{ required: true, message: '请选择' }],
      generateType: [{ required: true, message: '请选择' }],
      stock: [
        {
          required: true,
          type: 'number',
          min: 1,
          message: '请上传',
          trigger: 'blur'
        }
      ],
      perPersonLimit: [
        {
          required: true,
          trigger: 'blur',
          validator: numberValidator
        }
      ],
      date: [{ required: true, message: '请选择' }],
      discountAmount: [
        {
          required: true,
          trigger: 'blur',
          validator: numberValidator
        }
      ],
      discount: [
        {
          required: true,
          trigger: 'blur',
          validator: (rule, value) => {
            if (value === '' || value === null) {
              return Promise.reject('请输入')
            }

            if (isNaN(Number(value))) {
              return Promise.reject('请输入数字')
            }

            if (value > 1) {
              return Promise.reject('最大值为1')
            }

            return Promise.resolve()
          }
        }
      ]
    } as FormRules)
    const couponType = ref([
      {
        label: '签到券码',
        value: 1
      },
      {
        label: '拼团券码',
        value: 2
      },
      {
        label: '翻牌券码',
        value: 3
      },
      {
        label: '积分兑换券',
        value: 4
      },
      {
        label: '金豆兑好礼',
        value: 5
      }
    ])
    const genType = ref([
      {
        label: '手动导入',
        value: 1
      }
    ])
    const discountType = ref<0 | 1>(0)
    const fileList = ref<FileItem[]>([])
    const uploadSuccessNum = ref('')
    const uploadPath = ref('')
    const uploadFailNum = ref('')
    const showUploadResult = ref(false)
    const downloadLoading = ref(false)

    const isDisabled = computed(() => {
      if (props.isValid) {
        return false
      }

      if (props.isEdit) {
        return true
      }

      return false
    })

    const formRef = useForm(formModel, formRules)

    const { handleCancel } = useBack('refreshCouponManage')

    const couponId = computed(() => route.query.id as string)

    function numberValidator(rule, value) {
      if (value === '' || value === null) {
        return Promise.reject('请输入')
      }

      if (isNaN(Number(value))) {
        return Promise.reject('请输入数字')
      }

      return Promise.resolve()
    }

    async function handleExport() {
      try {
        loading.value = true
        const res = await couponApi.exportTemplate()
        download(res, '库存导入模板')
      } finally {
        loading.value = false
      }
    }

    async function handleUpload(params: any) {
      try {
        loading.value = true
        const formData = new FormData()
        formData.append('file', params.file)
        formData.append('serialNumber', formModel.value.serialNumber)

        if (props.isEdit) {
          formData.append('id', couponId.value)
        }

        const res = await couponApi.uploadTemplate(formData)

        fileList.value = [params.file]

        formModel.value.serialNumber = res.serialNumber as any
        formModel.value.stock = res.stock as any
        uploadFailNum.value = res.failNum as any
        uploadSuccessNum.value = res.successNum as any
        uploadPath.value = res.path

        showUploadResult.value = true
      } finally {
        loading.value = false
      }
    }

    function handleDownloadResult() {
      downloadLoading.value = true
      downloadLink(uploadPath.value, '券码')
      downloadLoading.value = false
      showUploadResult.value = false
    }

    function handleCloseUploadResult() {
      showUploadResult.value = false
    }

    function handleDeleteUploadResult() {
      fileList.value = []
      formModel.value.stock = (Number(formModel.value.stock) -
        Number(uploadSuccessNum.value)) as any
      formModel.value.serialNumber = ''
      uploadFailNum.value = ''
      uploadPath.value = ''
      uploadSuccessNum.value = ''
    }

    function handleSubmit() {
      const names = isDisabled.value
        ? ['stock']
        : [
            'name',
            'couponType',
            'generateType',
            'stock',
            'perPersonLimit',
            'date',
            discountType.value === 0 ? 'discountAmount' : 'discount'
          ]

      formRef
        .validate(names)
        .then(async () => {
          try {
            loading.value = true
            const data = {
              ...omit(formModel.value, ['date']),
              startDate: formModel.value.date[0],
              endDate: formModel.value.date[1]
            }
            props.isEdit
              ? await couponApi.updateOne(data)
              : await couponApi.createOne(data)
            notification.success({
              message: (props.isEdit ? '编辑' : '新建') + '优惠券成功',
              duration: 1.5
            })
            handleCancel()
          } finally {
            loading.value = false
          }
        })
        .catch(errors => {
          console.log(errors)
        })
    }

    async function init() {
      if (props.isEdit) {
        try {
          loading.value = true
          const res = await couponApi.getDetail(Number(couponId.value))
          Object.assign(formModel.value, omit(res, ['startDate', 'endDate']), {
            date: [res.startDate, res.endDate]
          })
          discountType.value = res.discount === null ? 0 : 1
        } finally {
          loading.value = false
        }
      }
    }

    /** 切换优惠规则时清除值和校验结果 */
    watch(discountType, val => {
      formRef.clearValidate()

      if (val === 0) {
        formModel.value.discount = ''
      } else {
        formModel.value.discountAmount = ''
      }
    })

    onMounted(() => {
      init()
    })

    return {
      loading,
      formModel,
      formRules,
      formRef,
      couponType,
      genType,
      discountType,
      isDisabled,
      fileList,
      uploadSuccessNum,
      uploadPath,
      uploadFailNum,
      showUploadResult,
      downloadLoading,
      handleExport,
      handleUpload,
      handleDownloadResult,
      handleCloseUploadResult,
      handleDeleteUploadResult,
      handleCancel,
      handleSubmit
    }
  },
  render() {
    return (
      <div>
        <Spin spinning={this.loading}>
          <Form labelCol={{ span: 2 }}>
            <div class={styles.formSection}>
              <h3 class={styles.title}>基本信息</h3>
              <FormItem
                label="优惠券名称"
                {...this.formRef.validateInfos['name']}
              >
                <Input
                  v-model:value={this.formModel.name}
                  v-slots={{
                    suffix: () => <span>{this.formModel.name.length}/9</span>
                  }}
                  class={styles.formInput}
                  maxlength={9}
                  disabled={this.isDisabled}
                />
                <span class={styles.desc}>
                  建议描述具体优惠，如：无门槛5元优惠券
                </span>
              </FormItem>
              <FormItem
                label="码类型"
                {...this.formRef.validateInfos['couponType']}
              >
                <RadioGroup
                  v-model:value={this.formModel.couponType}
                  disabled={this.isDisabled}
                >
                  {this.couponType.map(v => (
                    <Radio value={v.value}>{v.label}</Radio>
                  ))}
                </RadioGroup>
              </FormItem>
              <FormItem
                label="生成方式"
                {...this.formRef.validateInfos['generateType']}
              >
                <RadioGroup
                  v-model:value={this.formModel.generateType}
                  disabled={this.isDisabled}
                >
                  {this.genType.map(v => (
                    <Radio value={v.value}>{v.label}</Radio>
                  ))}
                </RadioGroup>
                <span class={styles.desc}>
                  已删除的码值可以重复使用，注意风险：码值遵循最新的活动优惠设置
                </span>
              </FormItem>
              <FormItem label="库存" {...this.formRef.validateInfos['stock']}>
                <Input
                  v-model:value={this.formModel.stock}
                  v-slots={{
                    addonAfter: () => '个'
                  }}
                  class={styles.formInput}
                  disabled
                />
                <div style={{ marginTop: '10px' }}>
                  <Upload
                    customRequest={this.handleUpload}
                    fileList={this.fileList}
                    showUploadList
                    remove={this.handleDeleteUploadResult}
                  >
                    {this.formModel.serialNumber === '' && (
                      <Button icon={<SvgIcon name="plus" />}>上传</Button>
                    )}
                  </Upload>
                </div>
                <div>
                  <Button
                    type="link"
                    size="small"
                    style={{ padding: 0 }}
                    onClick={this.handleExport}
                  >
                    下载导入模板
                  </Button>
                  <span class={styles.desc}>
                    每次最多50000个，每个码模板总库存最多200000个
                  </span>
                </div>
              </FormItem>
              <FormItem
                label="每人限用"
                {...this.formRef.validateInfos['perPersonLimit']}
              >
                <Input
                  v-model:value={this.formModel.perPersonLimit}
                  v-slots={{
                    addonAfter: () => '个'
                  }}
                  class={styles.formInput}
                  disabled={this.isDisabled}
                />
                <span class={styles.desc}>填0为不限制</span>
              </FormItem>
              <FormItem label="有效期" {...this.formRef.validateInfos['date']}>
                <RangePicker
                  v-model:value={this.formModel.date}
                  valueFormat="YYYY-MM-DD"
                  disabled={this.isDisabled}
                />
              </FormItem>
            </div>
            <div class={styles.formSection}>
              <h3 class={styles.title}>优惠规则</h3>
              <FormItem
                label={
                  <>
                    <Radio
                      checked={this.discountType === 0}
                      onChange={() => {
                        this.discountType = 0
                      }}
                      disabled={this.isDisabled}
                    ></Radio>
                    <span>减免金额</span>
                  </>
                }
                {...this.formRef.validateInfos['discountAmount']}
              >
                <Input
                  v-model:value={this.formModel.discountAmount}
                  v-slots={{
                    addonAfter: () => '元'
                  }}
                  class={styles.formInput}
                  disabled={this.isDisabled || this.discountType === 1}
                />
                <span class={styles.desc}>不能抵扣运费</span>
              </FormItem>
              <FormItem
                label={
                  <>
                    <Radio
                      checked={this.discountType === 1}
                      onChange={() => {
                        this.discountType = 1
                      }}
                      disabled={this.isDisabled}
                    ></Radio>
                    <span>折扣</span>
                  </>
                }
                {...this.formRef.validateInfos['discount']}
              >
                <Input
                  v-model:value={this.formModel.discount}
                  v-slots={{
                    addonAfter: () => '折'
                  }}
                  class={styles.formInput}
                  disabled={this.isDisabled || this.discountType === 0}
                />
                <span class={styles.desc}>不能抵扣运费</span>
              </FormItem>
            </div>
            <FormItem class={styles.formBtns} wrapperCol={{ span: 24 }}>
              <Space>
                <Button class={styles.formBtn} onClick={this.handleCancel}>
                  取消
                </Button>
                <Button
                  class={styles.formBtn}
                  type="primary"
                  onClick={this.handleSubmit}
                >
                  保存
                </Button>
              </Space>
            </FormItem>
          </Form>
        </Spin>
        {/* 上传结果 */}
        <Modal
          v-model:visible={this.showUploadResult}
          v-slots={{
            footer: () => (
              <>
                <Button
                  type="primary"
                  loading={this.downloadLoading}
                  onClick={this.handleDownloadResult}
                  disabled={!this.uploadPath}
                >
                  下载附件
                </Button>
                <Button onClick={this.handleCloseUploadResult}>关闭</Button>
              </>
            )
          }}
        >
          <div>
            导入成功
            <span style={{ color: 'red' }}>{this.uploadSuccessNum}</span>
            条，其中
            <span style={{ color: 'red' }}>{this.uploadFailNum}</span>
            条失败，具体查看下载的附件
          </div>
        </Modal>
      </div>
    )
  }
})
